#pragma once

#include <iostream>
#include <string>
#include <vector>
#include <queue>
#include "Log.hpp"    // 日志模块，用于记录日志
#include "Thread.hpp" // 线程模块，包含线程相关的功能
#include "Cond.hpp"   // 条件变量模块，用于线程间的同步
#include "Mutex.hpp"  // 互斥锁模块，用于线程间的同步

namespace ThreadPoolModule
{
    using namespace ThreadModule;   // 引入线程模块
    using namespace LogModule;      // 引入日志模块
    using namespace CondModule;     // 引入条件变量模块
    using namespace MutexModule;    // 引入互斥锁模块

    static const int g_num = 5; // 默认线程池中线程数量

    template <class T>
    class ThreadPool
    {
    private:
        // 唤醒所有处于等待状态的线程
        void WakeUpAllThread()
        {
            LockGuard guard(_mutex);  // 获取互斥锁，确保线程安全
            if (_sleep_thread)        // 如果有线程在等待
                _cond.Broadcast();    // 唤醒所有等待的线程
            LOG(LogLevel::INFO) << "wake up all thread!";
        }

        // 唤醒一个等待的线程
        void WakeUpOne()
        {
            _cond.Signal();  // 唤醒一个线程
            LOG(LogLevel::INFO) << " wake up one thread";
        }

        // 线程池构造函数
        ThreadPool(int num = g_num)
            : _num(num), _isrunning(false), _sleep_thread(0)
        {
            // 创建线程池中的所有线程，每个线程执行 HandlerTask() 方法
            for (int i = 0; i < num; i++)
            {
                _threads.emplace_back(
                    [this]()
                    {
                        HandlerTask(); // 线程执行任务处理函数
                    });
            }
        }

        // 启动线程池，启动每个线程
        void Start()
        {
            if (_isrunning) // 如果已经启动，则不再启动
                return;
            _isrunning = true; // 标记为已启动
            for (auto &th : _threads)
            {
                th.Start(); // 启动线程
                LOG(LogLevel::INFO) << "create new thread success";
            }
            return;
        }

        // 禁止拷贝构造函数和赋值操作
        ThreadPool(const ThreadPool<T>&) = delete;
        ThreadPool<T>& operator=(const ThreadPool<T>&) = delete;

    public:
        // 获取线程池的单例
        static ThreadPool<T>* GetInstance()
        {
            if(inc == nullptr)  // 如果单例尚未创建
            {
                LockGuard guard(_lock);  // 加锁，保证线程安全
                LOG(LogLevel::DEBUG) << "获取单例......";
                if(inc == nullptr)  // 确保仍然没有创建
                {
                    LOG(LogLevel::DEBUG) << "首次获取单例，创建之......";
                    inc = new ThreadPool<T>();  // 创建线程池
                    inc->Start();  // 启动线程池
                }
            }
            return inc;  // 返回线程池单例
        }

        // 线程处理任务的函数
        void HandlerTask()
        {
            char name[128];
            pthread_getname_np(pthread_self(), name, sizeof(name)); // 获取当前线程名称
            while (1)
            {
                T t;
                {
                    LockGuard gurad(_mutex);  // 获取互斥锁，确保线程安全
                    while (_taskq.empty() && _isrunning)  // 如果任务队列为空且线程池正在运行
                    {
                        _sleep_thread++;  // 增加等待线程数
                        _cond.Wait(_mutex);  // 当前线程等待
                        _sleep_thread--;  // 退出等待时减少等待线程数
                    }

                    if (!_isrunning && _taskq.empty())  // 如果线程池停止且任务队列为空
                    {
                        LOG(LogLevel::INFO) << name << " exit, threadpool exit and _taskq.empty()";
                        break;  // 退出线程
                    }

                    t = _taskq.front();  // 获取队列中的任务
                    _taskq.pop();  // 从队列中移除任务
                }
                t();  // 执行任务
            }
        }

        // 停止线程池，标记线程池为停止状态
        void Stop()
        {
            if (!_isrunning)  // 如果线程池已经停止
                return;
            _isrunning = false;  // 设置为停止状态

            WakeUpAllThread();  // 唤醒所有线程，让它们安全退出
        }

        // 等待所有线程执行完毕
        void Join()
        {
            for (auto& th : _threads)
                th.Join();  // 等待每个线程完成任务
            return;
        }

        // 向任务队列添加任务
        bool Enqueue(const T &in)
        {
            if (_isrunning)  // 如果线程池正在运行
            {
                LockGuard guard(_mutex);  // 获取互斥锁
                _taskq.push(in);  // 将任务添加到队列中
                if (_threads.size() == _sleep_thread)  // 如果所有线程都在等待
                    WakeUpOne();  // 唤醒一个线程来处理任务
                return true;
            }
            return false;  // 如果线程池已经停止，不能再添加任务
        }

        // 析构函数
        ~ThreadPool()
        {
            // 线程池析构时会自动处理资源释放
        }

    private:
        std::vector<Thread> _threads;  // 存储线程池中的所有线程
        int _num;  // 线程池中线程数量
        std::queue<T> _taskq;  // 存储任务的队列
        Cond _cond;  // 条件变量，用于线程间同步
        Mutex _mutex;  // 互斥锁，保护共享资源
        bool _isrunning;  // 标记线程池是否正在运行
        int _sleep_thread;  // 记录当前处于等待状态的线程数

        static ThreadPool<T>* inc;  // 单例指针
        static Mutex _lock;  // 用于单例的锁
    };

    // 初始化静态成员变量
    template<class T>
    ThreadPool<T>* ThreadPool<T>::inc = nullptr;

    template<class T>
    Mutex ThreadPool<T>::_lock;
}


// static ThreadPool<T>* GetInstance()
//         {
//             //ThreadPool();
//             //减少多线程创建单例竞争锁的情况
//             //多线程的情况下，还是可能会有两三个线程进入进去->74行竞争锁，一个线程获得锁创建单例
//             //单例创建后还是有一两个线程竞争锁，但是数量很少，在多线程环境下也是个优化
//             if(inc == nullptr)
//             {
//                 //单例创建可能被多线程获取，需要加锁
//                 LockGuard guard(_lock);
//                 LOG(LogLevel::DEBUG) << "获取单例......";
//                 if(inc == nullptr)
//                 {
//                     LOG(LogLevel::DEBUG) << "首次获取单例，创建之......";
//                     inc = new ThreadPool<T>();
//                     inc->Start();
//                 }
//             }
//             return inc;
//         }